<template>
  <n-card :bordered="false" class="proCard">
    <BasicTable
      :columns="columns"
      :request="loadDataTable"
      :row-key="(row) => row.id"
      ref="tableActionRef"
      :actionColumn="tableActionColumn"
      :scroll-x="920"
    >
      <template #tableTitle>
        <n-button type="primary" @click="dialogShow = true">
          上传
        </n-button>
      </template>
    </BasicTable>

    <n-modal
      v-model:show="dialogShow"
      style="width: 400px"
      preset="card"
      title="添加到图床"
      size="medium"
      :bordered="false"
    >
      <n-upload
        :action="`${global.urlPrefix}/picture/manual`"
        :headers="uploadHeaders"
        :accept="componentSetting.upload.fileType.toString()"
        :show-file-list="false"
        :on-finish="fileLoadFinish"
        :on-error="fileLoadError"
      >
        <n-upload-dragger>
          <div style="margin-bottom: 12px">
            <n-icon size="48" :depth="3">
              <ArchiveOutline />
            </n-icon>
          </div>
          <n-text style="font-size: 16px">
            点击或者拖动图片文件到该区域来上传
          </n-text>
          <n-p depth="3" style="margin: 8px 0 0 0">
            请不要上传敏感数据，比如身份证照片、银行卡照片等
          </n-p>
        </n-upload-dragger>
      </n-upload>
    </n-modal>
  </n-card>
</template>

<script lang="ts" setup>
import {h, reactive, ref, onMounted, onBeforeUnmount} from 'vue';
import {NButton, useDialog, useMessage} from "naive-ui";
import {columns} from "@/views/console/picture/columns";
import {BasicTable, TableAction} from '@/components/Table';
import {getPicturePage, upload2Picture, removePicture} from "@/api/console/picture";
import {getFilePreviewUrl} from "@/api/system/config";
import {useUserStore} from "@/store/modules/user";
import {useGlobSetting} from "@/hooks/setting";
import componentSetting from '@/settings/componentSetting';
import {Trash, ArchiveOutline, CopyOutline} from '@vicons/ionicons5';
import {AuthEnum, ResultEnum} from "@/enums/httpEnum";
import {encodePreviewUrl, generatorApiUrl} from "@/utils/urlUtils";

const global = useGlobSetting()
const userStore = useUserStore()
const message = useMessage()
const dialog = useDialog()

const pasteHandler = ev => {
  // 读取图片
  let items = ev.clipboardData && ev.clipboardData.items;
  let file: null | File = null;
  if (items && items.length) {
    // 检索剪切板items
    for (let i = 0; i < items.length; i++) {
      if (items[i].type.indexOf('image') !== -1) {
        file = items[i].getAsFile();
        break;
      }
    }
  }
  if (!file) {
    return message.warning('剪切板中未发现图片可上传!')
  }
  dialog.warning({
    title: '操作确认',
    content: '检测到[粘贴]快捷键, 是否将剪切板中的图片进行上传？',
    positiveText: '确定',
    negativeText: '取消',
    onPositiveClick: async () => {
      await upload2Picture(file)
      message.success('上传成功')
      reloadTable()
    },
    onNegativeClick: () => { }
  })
}

const filePreviewUrl = ref<string>()

onMounted(() => {
  document.addEventListener('paste', pasteHandler)
  // 获取文件预览的url
  getFilePreviewUrl().then(res => {
    const { code, data } = res;
    if (code === ResultEnum.SUCCESS) {
      filePreviewUrl.value = data
    }
  })
})

onBeforeUnmount(() => {
  document.removeEventListener('paste', pasteHandler)
})

const tableActionRef = ref();
const tableActionColumn = reactive({
  width: 120,
  title: '操作',
  key: 'action',
  fixed: 'right',
  align: 'center',
  render(row) {
    return h(TableAction, {
      style: 'text',
      actions: [
        {
          label: '链接',
          type: 'info',
          icon: CopyOutline,
          onClick: () => {
            const previewUrl = generatorApiUrl(`${row.filePath}`)
            // 将预览链接复制到剪切板中
            navigator.clipboard.writeText(previewUrl)
              .then(() => message.success('图片链接已复制到剪切板中'))
              .catch(e => {
                message.error('复制失败, 请重试')
                throw new Error(e)
              })
          }
        },
        {
          label: '预览',
          type: 'info',
          icon: CopyOutline,
          onClick: () => {
            const previewUrl = generatorApiUrl(`${row.filePath}`)
            if (!filePreviewUrl.value) {
              return message.warning('预览接口尚未接入，请联系管理员')
            }
            // 将预览链接复制到剪切板中
            navigator.clipboard.writeText(`${filePreviewUrl.value}${encodePreviewUrl(previewUrl)}`)
              .then(() => message.success('预览地址已复制到剪切板中'))
              .catch(e => {
                message.error('复制失败, 请重试')
                throw new Error(e)
              })
          }
        },
        {
          label: '移除',
          type: 'error',
          icon: Trash,
          onClick: () => {
            dialog.warning({
              title: '警告',
              content: '确定将该图片移除图床？',
              positiveText: '确定',
              negativeText: '取消',
              onPositiveClick: () => {
                removePicture(row.id)
                  .then(() => reloadTable())
                  .catch(() => dialog.destroyAll())
              },
              onNegativeClick: () => { }
            })
          }
        },
      ]
    })
  }
});

const loadDataTable = async (res) => {
  const data = await getPicturePage({pageNum: res.current, pageSize: res.size});
  // total 指的是总共多少条数据
  const { current, size, total, records } = data;
  return {
    current,
    size,
    count: Math.ceil(total / size),
    records,
  };
};

function reloadTable() {
  tableActionRef.value.reload();
}

const dialogShow = ref(false)
const uploadHeaders = ref({
  [AuthEnum.AUTH_TOKEN_HEADER]: `${AuthEnum.AUTH_TOKEN_SCHEME} ${userStore.token}`
})

const fileLoadFinish = () => {
  message.success('上传成功')
  dialogShow.value = false;
  reloadTable()
}

const fileLoadError = () => {
  message.warning('上传失败, 请重试')
}


</script>

<style lang="less" scoped>
:deep(.my-icon .n-button__icon) {
  margin: 0 !important;
}

:deep(div[class='n-input-group-label']) {
  --n-height: 40px !important;
}

:deep(.my-img) {
  height: 60px;
  cursor: pointer;
}
</style>
